/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "secure_element_agent.h"
#include "channel_stub.h"
#include "common_utils.h"
#include "loghelper.h"
#include "ipc_skeleton.h"
#include "se_common_exception.h"
#include "service_manager.h"
#include "service_impl.h"
#include "se_hisysevent.h"
#include "se_timer.h"

#include <unistd.h>
#include "idevmgr_hdi.h"
#include "hdf_remote_service.h"
#include "servmgr_hdi.h"
#include "se_hianalytics.h"

#define ESE_INTI_RETRY_TIME (1000 * 1000)

namespace OHOS {
namespace SE {
static const uint16_t SELECT_APDU_LEN_POS = 4;
static const uint16_t SELECT_APDU_HEAD_LEN = 5;
static const uint16_t SW1_OFFSET = 2;
static const uint16_t SW2_OFFSET = 1;
static const uint16_t WAIT_HDI_RESTART_TIME = 1;
HdfRemoteService *g_hdiService = nullptr;
constexpr const char *SE_HDI_NAME = "secure_element_interface_service";
constexpr const char *SE_SIM_HDI_NAME = "sim_secure_element_interface_service";
static const uint32_t TIMEOUT_CLOSE_SE = 8 * 60 * 1000;
uint32_t SecureElementAgent::closeChannelTimerId{0};

/**
 * @brief The HAL Service state change notification interface.
 */
class EseClientCallback : public EseISecureElementCallback {
public:
    explicit EseClientCallback(std::weak_ptr<SecureElementAgent> agent) : secureElementAgent_(agent)
    {}

    int32_t OnSeStateChanged(bool connected)
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (!secureElementAgent_.expired()) {
            secureElementAgent_.lock()->OnStateChange(connected);
        } else {
            WarnLog("EseClientCallback::OnSeStateChanged secureElementAgent_ expired.");
        }
        return HDF_SUCCESS;
    }

private:
    std::weak_ptr<SecureElementAgent> secureElementAgent_;
    // the mutex lock to access the secure element hdf
    std::mutex mutex_{};
};

class SimClientCallback : public SimISecureElementCallback {
public:
    explicit SimClientCallback(std::weak_ptr<SecureElementAgent> agent) : secureElementAgent_(agent)
    {}

    int32_t OnSeStateChanged(bool connected)
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (!secureElementAgent_.expired()) {
            secureElementAgent_.lock()->OnStateChange(connected);
        } else {
            WarnLog("SimClientCallback::OnSeStateChanged secureElementAgent_ expired.");
        }
        return HDF_SUCCESS;
    }

private:
    std::weak_ptr<SecureElementAgent> secureElementAgent_;
    // the mutex lock to access the secure element hdf
    std::mutex mutex_{};
};

SecureElementAgent::SecureElementAgent(std::string name)
{
    InfoLog("SecureElementAgent::SecureElementAgent seName_: %{public}s", name.c_str());
    secureElementConnected_ = false;
    seName_ = name;
}

SecureElementAgent::~SecureElementAgent()
{
    InfoLog("%{public}s SecureElementAgent::~SecureElementAgent", seName_.c_str());
    openChannels_.clear();
}

void SecureElementAgent::OnStateChange(bool connected)
{
    InfoLog("%{public}s SecureElementAgent::OnStateChange connected: %{public}d", seName_.c_str(), connected);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_SE_HAL_STATE, connected ? "success" : "fail");
    {
        std::lock_guard<std::mutex> lock(mutex_);
        if (!connected) {
            return;
        }
        secureElementConnected_ = connected;
    }

    auto iter = openChannels_.begin();
    while (iter != openChannels_.end()) {
        // don't lock(mutex_) here, do it in CloseChannels
        CloseChannels(iter->first);
        ++iter;
    }
    InfoLog("%{public}s SecureElementAgent::OnSeStateChanged done.", seName_.c_str());
}

/**
 * @brief Close Channel Timeout callback
 */
void SecureElementAgent::CloseChannelCallBack()
{
    std::lock_guard<std::mutex> lock(mutex_);
    InfoLog("%{public}s SecureElementAgent:: close channel timeout.", seName_.c_str());
    auto iter = openChannels_.begin();
    while (iter != openChannels_.end()) {
        // don't lock(mutex_) here, do it in CloseChannels
        CloseChannels(iter->first);
        ++iter;
    }
}

/**
 * @brief Create Close Channel Timer
 */
void SecureElementAgent::CreatCloseChannelTimer()
{
    InfoLog("%{public}s SecureElementAgent::CreatCloseChannelTimer start.", seName_.c_str());
    TimeOutCallback timeoutCallback = [this]() { SecureElementAgent::CloseChannelCallBack(); };
    if (closeChannelTimerId != 0) {
        SETimer::GetInstance()->UnRegister(closeChannelTimerId);  // ms
        closeChannelTimerId = 0;
    }
    SETimer::GetInstance()->Register(timeoutCallback, closeChannelTimerId, TIMEOUT_CLOSE_SE);
}

bool SecureElementAgent::EseInitialize()
{
    {
        int initCnt = 0;
        int initMaxTimes = 2;
        std::lock_guard<std::mutex> lock(mutex_);
        seEseHdiInterface_ = ISeEseHdiV1_0::Get();
        while (seEseHdiInterface_ == nullptr && initCnt < initMaxTimes) {
            usleep(ESE_INTI_RETRY_TIME);
            seEseHdiInterface_ = ISeEseHdiV1_0::Get();
            initCnt++;
        }
        InfoLog("Initialize HDF initCnt %{public}d", initCnt);
        seEseHdfCallback_ = new EseClientCallback(shared_from_this());
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("Initialize, ese %{public}s hdi interface null.", seName_.c_str());
            return false;
        }
    }

    AddHdiDeathRecipient();

    // NOTE: don't lock(mutex_) here, OnStateChange need lock mutex_
    EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seEseHdiInterface_->init(seEseHdfCallback_, status);
    if (ret != HDF_SUCCESS || status != EseSecureElementStatus::SE_SUCCESS) {
        ErrorLog("SecureElementAgent::EseInitialize ret = %{public}d, status = %{public}d", ret, status);
        return false;
    }
    return true;
}

bool SecureElementAgent::SimInitialize()
{
    {
        std::lock_guard<std::mutex> lock(mutex_);
        seSimHdiInterface_ = ISeSimHdiV1_0::Get(SE_SIM_HDI_NAME, false);
        seSimHdfCallback_ = new SimClientCallback(shared_from_this());
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("Initialize, sim %{public}s hdi interface null.", seName_.c_str());
            return false;
        }
    }

    AddHdiDeathRecipient();

    SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seSimHdiInterface_->init(seSimHdfCallback_, status);
    if (ret != HDF_SUCCESS || status != SimSecureElementStatus::SE_SUCCESS) {
        ErrorLog("SecureElementAgent::SimInitialize ret = %{public}d, status = %{public}d", ret, status);
        return false;
    }
    return true;
}

/**
 * @brief Call HDF to init the secure element.
 */
bool SecureElementAgent::Initialize()
{
    InfoLog("%{public}s SecureElementAgent::Initialize start", seName_.c_str());
    if (secureElementConnected_) {
        WarnLog("SeClientCallback::Initialize SecureElement has connected.");
        return true;
    }
    bool isAra = true;
    bool isArf = true;
    bool ret = true;

    if (seName_.compare(SE_NAME_ESE) == 0) {
        isAra = true;
        isArf = false;
        ret = EseInitialize();
    }
    if (seName_.compare(SE_NAME_SIM) == 0) {
        isAra = false;
        isArf = true;
        ret |= SimInitialize();
    }

    if (accessControlEnforcer_ == nullptr) {
        accessControlEnforcer_ =
            std::make_shared<AccessControlEnforcer>(AccessControlEnforcer(isAra, isArf, shared_from_this()));
        if (accessControlEnforcer_ == nullptr) {
            ErrorLog("Initialize, accessControlEnforcer_ is null.");
            return false;
        }
    }
    InfoLog("%{public}s SecureElementAgent::Initialize done ret = %{public}d", seName_.c_str(), ret);
    return ret;
}

/**
 * @brief Get the name for this secure element, eSE or SIM.
 * @return The name of this secure element
 */
std::string SecureElementAgent::GetName()
{
    // seName_ is only changed in constructor, no need to lock.
    return seName_;
}

/**
 * @brief Call HDF to check secure element present or not.
 * @return True if secure element present, otherwise false.
 */
bool SecureElementAgent::IsSecureElementPresent()
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        return false;
    }

    bool present = false;
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return false;
        }
        int32_t ret = seEseHdiInterface_->isSecureElementPresent(present);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return false;
        }
    } else if (seName_.compare(SE_NAME_SIM) == 0) {
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return false;
        }
        int32_t ret = seSimHdiInterface_->isSecureElementPresent(present);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return false;
        }
    }
    InfoLog("%{public}s IsSecureElementPresent true for %{public}d", seName_.c_str(), present);
    return present;
}

/**
 * @brief Call HDF to get the ART of this secure element.
 * @return The ATR of this secure element
 */
std::string SecureElementAgent::GetAtr()
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        return std::string{};
    }

    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return std::string{};
        }
        int32_t ret = seEseHdiInterface_->getAtr(vecResponse);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return std::string{};
        }
    } else if (seName_.compare(SE_NAME_SIM) == 0) {
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return std::string{};
        }
        int32_t ret = seSimHdiInterface_->getAtr(vecResponse);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return std::string{};
        }
    }

    std::string response =
        CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
    InfoLog("%{public}s GetAtr response %{public}s", seName_.c_str(), response.c_str());
    return response;
}

static void CheckEseStatusAndThrowException(EseSecureElementStatus status, const std::string &response = "")
{
    // the status is from secure element hdf.
    if (status == EseSecureElementStatus::SE_NO_SUCH_ELEMENT_ERROR) {
        throw NoSuchElementError("SE_NO_SUCH_ELEMENT_ERROR", response);
    } else if (status == EseSecureElementStatus::SE_OPERATION_NOT_SUPPORTED_ERROR) {
        throw UnsupportedOperationError("SE_OPERATION_NOT_SUPPORTED_ERROR", response);
    }
}

static void CheckSimStatusAndThrowException(SimSecureElementStatus status, const std::string &response = "")
{
    // the status is from secure element hdf.
    if (status == SimSecureElementStatus::SE_NO_SUCH_ELEMENT_ERROR) {
        throw NoSuchElementError("SE_NO_SUCH_ELEMENT_ERROR", response);
    } else if (status == SimSecureElementStatus::SE_OPERATION_NOT_SUPPORTED_ERROR) {
        throw UnsupportedOperationError("SE_OPERATION_NOT_SUPPORTED_ERROR", response);
    }
}

bool SecureElementAgent::OpenBasicChannelForEse(const std::string &aid, uint8_t p2, std::string &response)
{
    if (seEseHdiInterface_ == nullptr) {
        ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
        throw IllegalStateError("OpenBasicChannelForEse hdi interface null");
    }

    std::vector<uint8_t> vecAid;
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    CommonUtils::HexStringToBytesArray(aid, vecAid);
    EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seEseHdiInterface_->openBasicChannel(vecAid, p2, vecResponse, status);
    if (ret != HDF_SUCCESS) {
        ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
        return false;
    }

    response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
    InfoLog("%{public}s SecureElementAgent::OpenBasicChannelForEse response = %{public}s",
        seName_.c_str(),
        response.c_str());
    // Parse the chip response to check faults
    SeHisysEvent::WriteSeResponseHiSysEvent(response);
    // check the status from secure element hdf
    CheckEseStatusAndThrowException(status);
    if (status != EseSecureElementStatus::SE_SUCCESS) {
        ErrorLog("Error OpenBasicChannelForEse channel status %{public}d", status);
        return false;
    }
    return true;
}

bool SecureElementAgent::OpenBasicChannelForSim(const std::string &aid, uint8_t p2, std::string &response)
{
    if (seSimHdiInterface_ == nullptr) {
        ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
        throw IllegalStateError("OpenBasicChannelForSim hdi interface null");
    }

    std::vector<uint8_t> vecAid;
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    CommonUtils::HexStringToBytesArray(aid, vecAid);
    SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seSimHdiInterface_->openBasicChannel(vecAid, p2, vecResponse, status);
    if (ret != HDF_SUCCESS) {
        ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
        return false;
    }

    response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
    InfoLog("%{public}s SecureElementAgent::OpenBasicChannelForSim response = %{public}s",
        seName_.c_str(),
        response.c_str());
    // Parse the chip response to check faults
    SeHisysEvent::WriteSeResponseHiSysEvent(response);
    // check the status from secure element hdf
    CheckSimStatusAndThrowException(status);

    if (status != SimSecureElementStatus::SE_SUCCESS) {
        ErrorLog("Error OpenBasicChannelForSim channel status %{public}d", status);
        return false;
    }
    return true;
}

/**
 * @brief Get access to the basic channel, as defined in [ISO 7816-4] (the one that has number 0). The obtained
 * object is an instance of the channel class.
 * @param aid The AID of the applet to be selected on this channel, as a byte array, or Null if no applet is to be
 * selected.
 * @param p2 The P2 parameter of the SELECT APDU executed on this channel.
 * @return An instance of channel if available or Null.
 */
sptr<ChannelImpl> SecureElementAgent::OpenBasicChannel(const std::string &aid, uint8_t p2, std::string &response)
{
    std::string callingUniqueTag = CommonUtils::GetUniqueTag();
    DebugLog("%{public}s open channel aid = %{public}s, p2 = %{public}d", callingUniqueTag.c_str(), aid.c_str(), p2);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_BASIC_CHANNEL, "AID = " + aid, "p2 = " + std::to_string(p2));
    std::lock_guard<std::mutex> lock(mutex_);
    if (!secureElementConnected_) {
        SeHiAnalytics::GetInstance().SeEventLog(LOG_SECURE_ELEMENT_NO_CONNECT, LOG_DEFAULT_STR);
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        throw IllegalStateError("OpenBasicChannel secure element not connected");
    }

    // parse the aid and check the validation.
    uint32_t aidLength = CommonUtils::GetHexStringLength(aid);
    if (aidLength == 0 || (aidLength < AID_MIN_SIZE || aidLength > AID_MAX_SIZE)) {
        ErrorLog("OpenBasicChannel AID(length = %{public}d) invalid", aidLength);
        throw IllegalArgumentError("OpenBasicChannel AID is invalid");
    }

    if (IsBasicChannelBusy()) {
        ErrorLog("OpenBasicChannel, Basic channel is busy.");
        SeHiAnalytics::GetInstance().SeEventLog(LOG_BASIC_CHANNEL_IN_USE, LOG_DEFAULT_STR);
        throw ChannelNotAvailableError("Basic channel is busy");
    }

    if (!CheckChannelAccess(aid)) {
        ErrorLog("OpenBasicChannel, CheckChannelAccess false");
        throw AccessControlError("Applications not allowed to access basic channels.");
    }

    if (seName_.compare(SE_NAME_ESE) == 0 && !OpenBasicChannelForEse(aid, p2, response)) {
        SeHiAnalytics::GetInstance().SeEventLog(
            LOG_OPEN_BASIC_CHANNEL_NULL, "AID = " + aid, "p2 = " + std::to_string(p2));
        return sptr<ChannelImpl>{};
    } else if (seName_.compare(SE_NAME_SIM) == 0 && !OpenBasicChannelForSim(aid, p2, response)) {
        SeHiAnalytics::GetInstance().SeEventLog(
            LOG_OPEN_BASIC_CHANNEL_NULL, "AID = " + aid, "p2 = " + std::to_string(p2));
        return sptr<ChannelImpl>{};
    }

    // create the new basic channel.
    sptr<ChannelImpl> basicChannel =
        new (std::nothrow) ChannelImpl(shared_from_this(), true, BASIC_CHANNEL_ID, response);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_BASIC_CHANNEL_RESP, "selectResponse: " + response);
    openChannels_[callingUniqueTag].insert(std::make_pair(BASIC_CHANNEL_ID, basicChannel));
    InfoLog("%{public}s %{public}s open channel [%{public}d] success",
        seName_.c_str(),
        callingUniqueTag.c_str(),
        BASIC_CHANNEL_ID);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_BASIC_CHANNEL_SUCC, std::to_string(BASIC_CHANNEL_ID));
    return basicChannel;
}

sptr<ChannelImpl> SecureElementAgent::OpenBasicChannelWithoutChannelAccess(
    const std::string &aid, uint8_t p2, std::string &response)
{
    std::string callingUniqueTag = CommonUtils::GetUniqueTag();
    DebugLog("%{public}s open channel aid = %{public}s, p2 = %{public}d", callingUniqueTag.c_str(), aid.c_str(), p2);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        throw IllegalStateError("OpenBasicChannel secure element not connected");
    }

    // parse the aid and check the validation.
    uint32_t aidLength = CommonUtils::GetHexStringLength(aid);
    if (aidLength == 0 || (aidLength < AID_MIN_SIZE || aidLength > AID_MAX_SIZE)) {
        ErrorLog("OpenBasicChannel AID(length = %{public}d) invalid", aidLength);
        throw IllegalArgumentError("OpenBasicChannel AID is invalid");
    }

    if (IsBasicChannelBusy()) {
        ErrorLog("OpenBasicChannel, Basic channel is busy.");
        throw ChannelNotAvailableError("Basic channel is busy");
    }

    if (seName_.compare(SE_NAME_ESE) == 0 && !OpenBasicChannelForEse(aid, p2, response)) {
        return sptr<ChannelImpl>{};
    } else if (seName_.compare(SE_NAME_SIM) == 0 && !OpenBasicChannelForSim(aid, p2, response)) {
        return sptr<ChannelImpl>{};
    }

    // create the new basic channel.
    sptr<ChannelImpl> basicChannel =
        new (std::nothrow) ChannelImpl(shared_from_this(), true, BASIC_CHANNEL_ID, response);
    openChannels_[callingUniqueTag].insert(std::make_pair(BASIC_CHANNEL_ID, basicChannel));
    InfoLog("%{public}s %{public}s open channel [%{public}d] success",
        seName_.c_str(),
        callingUniqueTag.c_str(),
        BASIC_CHANNEL_ID);
    return basicChannel;
}

bool SecureElementAgent::OpenLogicalChannelForEse(
    const std::string &aid, uint8_t p2, uint8_t &channelNumber, std::string &response)
{
    if (seEseHdiInterface_ == nullptr) {
        ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
        throw IllegalStateError("OpenLogicalChannelForEse hdi interface null");
    }

    std::vector<uint8_t> vecAid;
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    CommonUtils::HexStringToBytesArray(aid, vecAid);
    EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seEseHdiInterface_->openLogicalChannel(vecAid, p2, vecResponse, channelNumber, status);
    if (ret != HDF_SUCCESS) {
        ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
        return false;
    }
    response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
    InfoLog("%{public}s SecureElementAgent::OpenLogicalChannelForEse response = %{public}s",
        seName_.c_str(),
        response.c_str());

    // Parse the chip response to check faults
    SeHisysEvent::WriteSeResponseHiSysEvent(response);
    // check the status from secure element hdf
    CheckEseStatusAndThrowException(status);

    if (channelNumber == 0 || status != EseSecureElementStatus::SE_SUCCESS) {
        ErrorLog(
            "Error OpenLogicalChannelForEse channelNumber = %{public}d, status = %{public}d", channelNumber, status);
        return false;
    }
    return true;
}

bool SecureElementAgent::OpenLogicalChannelForSim(
    const std::string &aid, uint8_t p2, uint8_t &channelNumber, std::string &response)
{
    if (seSimHdiInterface_ == nullptr) {
        ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
        throw IllegalStateError("OpenLogicalChannelForSim hdi interface null");
    }

    std::vector<uint8_t> vecAid;
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    CommonUtils::HexStringToBytesArray(aid, vecAid);
    SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
    int32_t ret = seSimHdiInterface_->openLogicalChannel(vecAid, p2, vecResponse, channelNumber, status);
    if (ret != HDF_SUCCESS) {
        ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
        return false;
    }
    response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
    InfoLog("%{public}s SecureElementAgent::OpenLogicalChannelForSim response = %{public}s",
        seName_.c_str(),
        response.c_str());

    // Parse the chip response to check faults
    SeHisysEvent::WriteSeResponseHiSysEvent(response);
    // check the status from secure element hdf
    CheckSimStatusAndThrowException(status);

    if (channelNumber == 0 || status != SimSecureElementStatus::SE_SUCCESS) {
        ErrorLog("Error openLogicalChannel channelNumber = %{public}d, status = %{public}d", channelNumber, status);
        return false;
    }
    return true;
}

/**
 * @brief Open a logical channel with the SE, selecting the applet represented by the given AID (when the AID is not
 * Null and the length of the AID is not 0).
 * @param aid The AID of the applet to be selected on this channel, as a byte array.
 * @param p2 The P2 parameter of the SELECT APDU executed on this channel.
 * @return An instance of channel. Null if the SE is unable to provide a new logical channel or is unable to
 * retrieve Access Control rules due to the lack of an available logical channel.
 */
sptr<ChannelImpl> SecureElementAgent::OpenLogicalChannel(const std::string &aid, uint8_t p2, std::string &response)
{
    std::string callingUniqueTag = CommonUtils::GetUniqueTag();
    DebugLog("%{public}s open channel aid = %{public}s, p2 = %{public}d", callingUniqueTag.c_str(), aid.c_str(), p2);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_LOGICAL_CHANNEL, "AID = " + aid, "p2 = " + std::to_string(p2));
    std::lock_guard<std::mutex> lock(mutex_);
    if (!secureElementConnected_) {
        SeHiAnalytics::GetInstance().SeEventLog(LOG_SECURE_ELEMENT_NO_CONNECT, LOG_DEFAULT_STR);
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        throw IllegalStateError("OpenLogicalChannel secure element not connected");
    }

    // parse the aid and check the validation.
    uint32_t aidLength = CommonUtils::GetHexStringLength(aid);
    if (aidLength == 0 || (aidLength < AID_MIN_SIZE || aidLength > AID_MAX_SIZE)) {
        ErrorLog("OpenLogicalChannel AID(length = %{public}d) invalid", aidLength);
        throw IllegalArgumentError("OpenLogicalChannel AID is invalid");
    }

    if (!CheckChannelAccess(aid)) {
        ErrorLog("OpenBasicChannel, CheckChannelAccess false");
        throw AccessControlError("Applications not allowed to access logical channels.");
    }

    // open logical channel by secure element hdf.
    uint8_t channelNumber = 0;
    if (seName_.compare(SE_NAME_ESE) == 0 && !OpenLogicalChannelForEse(aid, p2, channelNumber, response)) {
        SeHiAnalytics::GetInstance().SeEventLog(
            LOG_OPEN_LOGICAL_CHANNEL_NULL, "AID = " + aid, "p2 = " + std::to_string(p2));
        return sptr<ChannelImpl>();
    } else if (seName_.compare(SE_NAME_SIM) == 0 && !OpenLogicalChannelForSim(aid, p2, channelNumber, response)) {
        SeHiAnalytics::GetInstance().SeEventLog(
            LOG_OPEN_LOGICAL_CHANNEL_NULL, "AID = " + aid, "p2 = " + std::to_string(p2));
        return sptr<ChannelImpl>();
    }

    // create the new logical channel.
    sptr<ChannelImpl> logicalChannel =
        new (std::nothrow) ChannelImpl(shared_from_this(), false, channelNumber, response);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_LOGICAL_CHANNEL_RESP, "selectResponse: " + response);
    openChannels_[callingUniqueTag].insert(std::make_pair(channelNumber, logicalChannel));
    InfoLog("%{public}s %{public}s open channel [%{public}d] success",
        seName_.c_str(),
        callingUniqueTag.c_str(),
        channelNumber);
    SeHiAnalytics::GetInstance().SeEventLog(LOG_OPEN_LOGICAL_CHANNEL_SUCC, std::to_string(channelNumber));
    return logicalChannel;
}

sptr<ChannelImpl> SecureElementAgent::OpenLogicalChannelWithoutChannelAccess(
    const std::string &aid, uint8_t p2, std::string &response)
{
    std::string callingUniqueTag = CommonUtils::GetUniqueTag();
    InfoLog("%{public}s open channel aid = %{public}s, p2 = %{public}d", callingUniqueTag.c_str(), aid.c_str(), p2);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        throw IllegalStateError("OpenLogicalChannelWithoutChannelAccess secure element not connected");
    }

    // parse the aid and check the validation.
    uint32_t aidLength = CommonUtils::GetHexStringLength(aid);
    if (aidLength == 0 || (aidLength < AID_MIN_SIZE || aidLength > AID_MAX_SIZE)) {
        ErrorLog("OpenLogicalChannelWithoutChannelAccess AID(length = %{public}d) invalid", aidLength);
        throw IllegalArgumentError("OpenLogicalChannelWithoutChannelAccess AID is invalid");
    }

    // open logical channel by secure element hdf.
    uint8_t channelNumber = 0;
    if (seName_.compare(SE_NAME_ESE) == 0 && !OpenLogicalChannelForEse(aid, p2, channelNumber, response)) {
        return sptr<ChannelImpl>();
    } else if (seName_.compare(SE_NAME_SIM) == 0 && !OpenLogicalChannelForSim(aid, p2, channelNumber, response)) {
        return sptr<ChannelImpl>();
    }

    // create the new logical channel.
    sptr<ChannelImpl> logicalChannel =
        new (std::nothrow) ChannelImpl(shared_from_this(), false, channelNumber, response);
    openChannels_[callingUniqueTag].insert(std::make_pair(channelNumber, logicalChannel));
    InfoLog("%{public}s %{public}s OpenLogicalChannelWithoutChannelAccess [%{public}d] success",
        seName_.c_str(),
        callingUniqueTag.c_str(),
        channelNumber);
    return logicalChannel;
}

/**
 * @brief Transmit an APDU command (as per ISO/IEC 7816) to the SE.
 * @param command The APDU command to be transmitted, as a byte array.
 * @return The response received, as a byte array. The returned byte array contains the data bytes in the following
 * order: {<first data byte>, …, <last data byte>, <sw1>, <sw2>}.
 */
std::string SecureElementAgent::Transmit(const std::string &cmd)
{
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_NULL_BUNDLE, seName_);
        throw IllegalStateError("Transmit secure element not connected");
    }
    std::vector<uint8_t> vecCommand;
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    std::string response{};
    SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_CMD, "cmd: " + cmd);
    CommonUtils::HexStringToBytesArray(cmd, vecCommand);
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_EXCEPTION, seName_);
            throw IllegalStateError("Transmit hdi interface null");
        }
        EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seEseHdiInterface_->transmit(vecCommand, vecResponse, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_RESP_EMPTY, LOG_DEFAULT_STR);
            return std::string{};
        }
        // check response: when sw1 is 0x6C or Ox61, need to handle
        EseResponseCheckAndHandle(vecCommand, vecResponse, status);
        response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
        SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_RSP, "rsp: " + response);
        SeHisysEvent::WriteSeResponseHiSysEvent(cmd, response);
        // check the status from secure element hdf
        CheckEseStatusAndThrowException(status, response);
    } else if (seName_.compare(SE_NAME_SIM) == 0) {
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_EXCEPTION, seName_);
            throw IllegalStateError("Transmit hdi interface null");
        }
        SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seSimHdiInterface_->transmit(vecCommand, vecResponse, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_RESP_EMPTY, LOG_DEFAULT_STR);
            return std::string{};
        }

        // check response: when sw1 is 0x6C or Ox61, need to handle
        SimResponseCheckAndHandle(vecCommand, vecResponse, status);
        response = CommonUtils::BytesArrayToHexString(static_cast<uint8_t *>(vecResponse.data()), vecResponse.size());
        SeHiAnalytics::GetInstance().SeEventLog(LOG_TRANSMIT_RSP, "rsp: " + response);
        SeHisysEvent::WriteSeResponseHiSysEvent(cmd, response);
        // check the status from secure element hdf
        CheckSimStatusAndThrowException(status);
    }
    return response;
}

void SecureElementAgent::EseResponseCheckAndHandle(
    std::vector<uint8_t> &vecCommand, std::vector<uint8_t> &vecResponse, EseSecureElementStatus &status)
{
    if (vecResponse.size() < SW1_OFFSET || vecCommand.size() < SW2_OFFSET) {
        WarnLog("vecResponse size = %{public}lu, cmd size = %{public}lu", vecResponse.size(), vecCommand.size());
        return;
    }
    int sw1 = vecResponse[vecResponse.size() - SW1_OFFSET] & 0xFF;
    int sw2 = vecResponse[vecResponse.size() - SW2_OFFSET] & 0xFF;
    if (sw1 == 0x6C) {
        InfoLog("%{public}s ResponseCheckAndHandle, sw1 = %{public}0x, sw2 = %{public}0x", seName_.c_str(), sw1, sw2);
        vecCommand[vecCommand.size() - SW2_OFFSET] = vecResponse[vecResponse.size() - SW2_OFFSET];
        int32_t ret = seEseHdiInterface_->transmit(vecCommand, vecResponse, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("Transmit failed ret %{public}d, status %{public}d", ret, status);
            return;
        }
    }
    if (sw1 == 0x61) {
        do {
            InfoLog(
                "%{public}s ResponseCheckAndHandle, sw1 = %{public}0x, sw2 = %{public}0x", seName_.c_str(), sw1, sw2);
            std::vector<uint8_t> getResponseCmd = {vecCommand[0], 0xC0, 0x00, 0x00, sw2};
            std::vector<uint8_t> tmp;
            int32_t ret = seEseHdiInterface_->transmit(getResponseCmd, tmp, status);
            if (ret != HDF_SUCCESS) {
                ErrorLog("Transmit failed ret %{public}d, status %{public}d", ret, status);
                return;
            }
            if (tmp.size() < SW1_OFFSET) {
                WarnLog("tmp response size = %{public}lu", tmp.size());
                return;
            }
            std::vector<uint8_t> aux = vecResponse;
            vecResponse.clear();
            vecResponse.insert(vecResponse.end(), aux.begin(), aux.end() - SW1_OFFSET);
            vecResponse.insert(vecResponse.end(), tmp.begin(), tmp.end());
            sw1 = vecResponse[vecResponse.size() - SW1_OFFSET] & 0xFF;
            sw2 = vecResponse[vecResponse.size() - SW2_OFFSET] & 0xFF;
        } while (sw1 == 0x61);
    }
}

void SecureElementAgent::SimResponseCheckAndHandle(
    std::vector<uint8_t> &vecCommand, std::vector<uint8_t> &vecResponse, SimSecureElementStatus &status)
{
    if (vecResponse.size() < SW1_OFFSET || vecCommand.size() < SW2_OFFSET) {
        WarnLog("vecResponse size = %{public}lu, cmd size = %{public}lu", vecResponse.size(), vecCommand.size());
        return;
    }
    int sw1 = vecResponse[vecResponse.size() - SW1_OFFSET] & 0xFF;
    int sw2 = vecResponse[vecResponse.size() - SW2_OFFSET] & 0xFF;
    if (sw1 == 0x6C) {
        InfoLog("%{public}s ResponseCheckAndHandle, sw1 = %{public}0x", seName_.c_str(), sw1);
        vecCommand[vecCommand.size() - SW2_OFFSET] = vecResponse[vecResponse.size() - SW2_OFFSET];
        int32_t ret = seSimHdiInterface_->transmit(vecCommand, vecResponse, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("Transmit failed ret %{public}d, status %{public}d", ret, status);
            return;
        }
    }
    if (sw1 == 0x61) {
        do {
            InfoLog("%{public}s ResponseCheckAndHandle, sw1 = %{public}0x", seName_.c_str(), sw1);
            std::vector<uint8_t> getResponseCmd = {vecCommand[0], 0xC0, 0x00, 0x00, sw2};
            std::vector<uint8_t> tmp;
            int32_t ret = seSimHdiInterface_->transmit(getResponseCmd, tmp, status);
            if (ret != HDF_SUCCESS) {
                ErrorLog("Transmit failed ret %{public}d, status %{public}d", ret, status);
                return;
            }
            if (tmp.size() < SW1_OFFSET) {
                WarnLog("tmp response size = %{public}lu", tmp.size());
                return;
            }
            std::vector<uint8_t> aux = vecResponse;
            vecResponse.clear();
            vecResponse.insert(vecResponse.end(), aux.begin(), aux.end() - SW1_OFFSET);
            vecResponse.insert(vecResponse.end(), tmp.begin(), tmp.end());
            sw1 = vecResponse[vecResponse.size() - SW1_OFFSET] & 0xFF;
            sw2 = vecResponse[vecResponse.size() - SW2_OFFSET] & 0xFF;
        } while (sw1 == 0x61);
    }
}

/**
 * Selects the default application on the basic channel.
 *
 * If there is an exception selecting the default application, select
 * is performed with the default access control aid.
 */
void SecureElementAgent::SelectDefaultApplication()
{
    int32_t ret = HDF_SUCCESS;
    std::vector<uint8_t> aidSlect;
    ret = SelectCmd(aidSlect);
    if (ret != HDF_SUCCESS) {
        ErrorLog("SelectCmd failed ret %{public}d", ret);
    }
    return;
}

int32_t SecureElementAgent::SelectCmd(const std::vector<uint8_t> &aid)
{
    std::vector<uint8_t> selectCommand;
    int32_t ret = HDF_SUCCESS;
    int sw1 = 0;
    int sw2 = 0;
    uint8_t headCmd[SELECT_APDU_HEAD_LEN] = {0x00, 0xA4, 0x04, 0x00, 0x00};
    if (!aid.empty()) {
        headCmd[SELECT_APDU_LEN_POS] = aid.size();
        selectCommand.insert(selectCommand.begin(), headCmd, headCmd + SELECT_APDU_HEAD_LEN);
        selectCommand.insert(selectCommand.begin() + SELECT_APDU_HEAD_LEN, aid.begin(), aid.end());
    } else {
        headCmd[SELECT_APDU_LEN_POS] = 0x00;
        selectCommand.insert(selectCommand.begin(), headCmd, headCmd + SELECT_APDU_HEAD_LEN);
    }
    std::vector<uint8_t> vecResponse(MAX_APDU_RESP_BYTES, 0);
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            throw IllegalStateError("Transmit hdi interface null");
        }
        EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
        ret = seEseHdiInterface_->transmit(selectCommand, vecResponse, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return ret;
        }
        sw1 = vecResponse[vecResponse.size() - SW1_OFFSET] & 0xFF;
        sw2 = vecResponse[vecResponse.size() - SW2_OFFSET] & 0xFF;
        if (sw1 != 0x90 || sw2 != 0x00) {
            ErrorLog("%{public}s response is 0x%{public}0x, 0x%{public}0x.", seName_.c_str(), sw1, sw2);
            return HDF_FAILURE;
        }
    }
    InfoLog("%{public}s Select, sw1 = 0x%{public}0x, sw2 = 0x%{public}0x", seName_.c_str(), sw1, sw2);
    return HDF_SUCCESS;
}

int32_t SecureElementAgent::ChannelPreProcess(uint8_t channelNum, bool isBasicChannel)
{
    if (isBasicChannel && channelNum != BASIC_CHANNEL_ID) {
        ErrorLog("CloseChannel, basic channel number %{public}d", channelNum);
        return HDF_FAILURE;
    }
    if (!isBasicChannel && channelNum == BASIC_CHANNEL_ID) {
        ErrorLog("CloseChannel, logical channel number %{public}d", channelNum);
        return HDF_FAILURE;
    }
    if (isBasicChannel && channelNum == BASIC_CHANNEL_ID) {
        SelectDefaultApplication();
    }
    return HDF_SUCCESS;
}

bool SecureElementAgent::IsBasicChannelBusy()
{
    auto iter = openChannels_.begin();
    while (iter != openChannels_.end()) {
        if ((iter->second).find(BASIC_CHANNEL_ID) != (iter->second).end()) {
            return true;
        }
        ++iter;
    }
    return false;
}

bool SecureElementAgent::CheckChannelAccess(const std::string &aid)
{
    if (accessControlEnforcer_->IsChannelAccessAllowed(IPCSkeleton::GetCallingUid())) {
        return true;
    }

    if (seName_.compare(SE_NAME_SIM) == 0 &&
        accessControlEnforcer_->IsAllowedByFingerPrint(IPCSkeleton::GetCallingUid())) {
        InfoLog("access granted.");
        return true;
    }

    std::vector<uint8_t> vecTmpAid;
    CommonUtils::HexStringToBytesArray(aid, vecTmpAid);
    if (accessControlEnforcer_->IsAllowedByAidAndAppId(vecTmpAid, IPCSkeleton::GetCallingUid())) {
        return true;
    }
    return false;
}

/**
 * @brief Call HDF to close specific channel for this secure element.
 * @param channelNum The channel number to be closed.
 * @param isBasicChannel Is basic chennel or not.
 */
void SecureElementAgent::CloseChannel(uint8_t channelNum, bool isBasicChannel, const std::string &callingUniqueTag)
{
    InfoLog("%{public}s %{public}s ready to close channel [%{public}d].", seName_.c_str(), callingUniqueTag.c_str(),
        channelNum);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        return;
    }
    int32_t ret = ChannelPreProcess(channelNum, isBasicChannel);
    if (ret != HDF_SUCCESS) {
        ErrorLog("%{public}s ChannelPreProcess failed", seName_.c_str());
        return;
    }
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return;
        }
        EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seEseHdiInterface_->closeChannel(channelNum, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return;
        }
        if (status != EseSecureElementStatus::SE_SUCCESS) {
            ErrorLog("%{public}s failed,  channel status %{public}d", seName_.c_str(), status);
            return;
        }
    } else if (seName_.compare(SE_NAME_SIM) == 0) {
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return;
        }
        SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seSimHdiInterface_->closeChannel(channelNum, status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return;
        }
        if (status != SimSecureElementStatus::SE_SUCCESS) {
            ErrorLog("%{public}s failed,  channel status %{public}d", seName_.c_str(), status);
            return;
        }
    }
    openChannels_[callingUniqueTag][channelNum]->SetChannelState(true);
    openChannels_[callingUniqueTag].erase(channelNum);
    InfoLog("%{public}s %{public}s close channel [%{public}d] success.", seName_.c_str(), callingUniqueTag.c_str(),
        channelNum);
}

/**
 * @brief Close all chennels for this secure element. Call CloseChannel(channel) to close each channel.
 */
void SecureElementAgent::CloseChannels(const std::string &callingUniqueTag)
{
    std::vector<wptr<ChannelImpl>> channels;
    {
        std::lock_guard<std::mutex> lock(mutex_);
        InfoLog("%{public}s %{public}s reday to close all channels.", seName_.c_str(), callingUniqueTag.c_str());
        if (openChannels_.empty()) {
            WarnLog("CloseChannels, channel is empty.");
            return;
        }

        auto iter = openChannels_.find(callingUniqueTag);
        if (iter != openChannels_.end()) {
            std::map<uint8_t, sptr<ChannelImpl>>::iterator iter1 = iter->second.begin();
            while (iter1 != iter->second.end()) {
                channels.push_back(iter1->second);
                InfoLog("%{public}s SecureElementAgent::CloseChannels iter cnt.", seName_.c_str());
                ++iter1;
            }
        } else {
            WarnLog("%{public}s not found.", callingUniqueTag.c_str());
        }
    }

    // close all the se channels, don't guard(mutex_) here again, do it CloseChannel.
    for (wptr<ChannelImpl> &channel : channels) {
        uint8_t channelNumber = 0;
        bool isBasicChannel = false;
        channel.promote()->GetChannelNumber(channelNumber);
        channel.promote()->IsBasicChannel(isBasicChannel);
        InfoLog(
            "%{public}s SecureElementAgent::CloseChannels channelNumber %{public}d.", seName_.c_str(), channelNumber);
        if (!isBasicChannel) {
            SeHiAnalytics::GetInstance().SeEventLog(
                LOG_CLOSE_UNCLOSE_CHANNEL, "close unclose ChannelNum:" + std::to_string(channelNumber));
        }
        CloseChannel(channelNumber, isBasicChannel, callingUniqueTag);
    }

    {
        std::lock_guard<std::mutex> lock(mutex_);
        openChannels_.erase(callingUniqueTag);
    }
    InfoLog("%{public}s %{public}s close all channels success.", seName_.c_str(), callingUniqueTag.c_str());
}

/**
 * @brief Call HDF to reset the secure element.
 */
bool SecureElementAgent::Reset()
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (!secureElementConnected_) {
        ErrorLog("%{public}s failed, secure element not connected", seName_.c_str());
        return false;
    }
    if (seName_.compare(SE_NAME_ESE) == 0) {
        if (seEseHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return false;
        }
        EseSecureElementStatus status = EseSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seEseHdiInterface_->reset(status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return false;
        }
        if (status != EseSecureElementStatus::SE_SUCCESS) {
            ErrorLog("%{public}s failed,  channel status %{public}d", seName_.c_str(), status);
            return false;
        }
    } else if (seName_.compare(SE_NAME_SIM) == 0) {
        if (seSimHdiInterface_ == nullptr) {
            ErrorLog("%{public}s failed, hdi interface null.", seName_.c_str());
            return false;
        }
        SimSecureElementStatus status = SimSecureElementStatus::SE_GENERAL_ERROR;
        int32_t ret = seSimHdiInterface_->reset(status);
        if (ret != HDF_SUCCESS) {
            ErrorLog("%{public}s failed, ret %{public}d", seName_.c_str(), ret);
            return false;
        }
        if (status != SimSecureElementStatus::SE_SUCCESS) {
            ErrorLog("%{public}s failed,  channel status %{public}d", seName_.c_str(), status);
            return false;
        }
    }
    InfoLog("%{public}s Reset success.", seName_.c_str());
    return true;
}

void SecureElementAgent::ReleaseByCallingTokenId(const std::string &callingUniqueTag)
{
    // NOTE: don't lock(mutex_) here, do it in CloseChannels.
    CloseChannels(callingUniqueTag);
    InfoLog("%{public}s %{public}s call, openChannels_.size() = %{public}lu",
        seName_.c_str(),
        callingUniqueTag.c_str(),
        openChannels_.size());
}

/**
 * @brief Monitor whether the nfc_host process is dead.
 */
void SecureElementAgent::AddHdiDeathRecipient()
{
    struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();
    if (serviceMgr == nullptr) {
        ErrorLog("HDIServiceManagerGet failed!");
        return;
    }
    g_hdiService = serviceMgr->GetService(serviceMgr, SE_HDI_NAME);
    HDIServiceManagerRelease(serviceMgr);
    if (g_hdiService == nullptr) {
        ErrorLog("Remote GetService [g_hdiService] failed!");
        return;
    }
    static HdfDeathRecipient recipient = {
        .OnRemoteDied = [](HdfDeathRecipient *deathRecipient, HdfRemoteService *service) {
            InfoLog("Hdi service died! reload service");
            RemoveHdiDeathRecipient();
            sleep(WAIT_HDI_RESTART_TIME);
            _exit(0);
        }};
    HdfRemoteServiceAddDeathRecipient(g_hdiService, &recipient);
    InfoLog("Hdi service add death recipient success!");
}

/**
 * @brief Remove monitor whether the nfc_host process is dead.
 */
void SecureElementAgent::RemoveHdiDeathRecipient()
{
    if (g_hdiService != nullptr) {
        HdfRemoteServiceRemoveDeathRecipient(g_hdiService, nullptr);
        g_hdiService = nullptr;
    }
}
}  // namespace SE
}  // namespace OHOS